/* eslint-disable no-useless-escape, unicorn/prefer-string-slice */

/**
 * 2020.11.29 lyt 整理
 * 工具类集合，适用于平时开发
 * 新增多行注释信息，鼠标放到方法名即可查看
 */

/**
 * 验证百分比（不可以小数）
 * @param {string} value 当前值字符串
 * @returns {string} 返回处理后的字符串
 */
export function verifyNumberPercentage(value: string): string {
  // 匹配空格
  let v = value.replaceAll(/(^\s*)|(\s*$)/g, '')
  // 只能是数字和小数点，不能是其他输入
  v = v.replaceAll(/\D/g, '')
  // 不能以0开始
  v = v.replaceAll(/^0/g, '')
  // 数字超过100，赋值成最大值100
  v = v.replace(/^[1-9]\d{2,4}$/, '100')
  // 返回结果
  return v
}

/**
 * 验证百分比（可以小数）
 * @param {string} value 当前值字符串
 * @returns {string} 返回处理后的字符串
 */
export function verifyNumberPercentageFloat(value: string): string {
  let v = verifyNumberIntegerAndFloat(value)
  // 数字超过100，赋值成最大值100
  v = v.replace(/^[1-9]\d{2,4}$/, '100')
  // 超过100之后不给再输入值
  v = v.replace(/^100\.$/, '100')
  // 返回结果
  return v
}

/**
 * 小数或整数(不可以负数)
 * @param {string} value 当前值字符串
 * @returns {string} 返回处理后的字符串
 */
export function verifyNumberIntegerAndFloat(value: string) {
  // 匹配空格
  let v = value.replaceAll(/(^\s*)|(\s*$)/g, '')
  // 只能是数字和小数点，不能是其他输入
  v = v.replaceAll(/[^\d.]/g, '')
  // 以0开始只能输入一个
  v = v.replaceAll(/^0{2}$/g, '0')
  // 保证第一位只能是数字，不能是点
  v = v.replaceAll(/^\./g, '')
  // 小数只能出现1位
  v = v.replace('.', '$#$').replaceAll('.', '').replace('$#$', '.')
  // 小数点后面保留2位
  v = v.replace(/^(-)*(\d+)\.(\d\d).*$/, '$1$2.$3')
  // 返回结果
  return v
}

/**
 * 正整数验证
 * @param {string} value 当前值字符串
 * @returns {string} 返回处理后的字符串
 */
export function verifiyNumberInteger(value: string) {
  // 匹配空格
  let v = value.replaceAll(/(^\s*)|(\s*$)/g, '')
  // 去掉 '.' , 防止贴贴的时候出现问题 如 0.1.12.12
  v = v.replaceAll(/\.*/g, '')
  // 去掉以 0 开始后面的数, 防止贴贴的时候出现问题 如 00121323
  v = v.replaceAll(/(^0\d*)$/g, '0')
  // 首位是0,只能出现一次
  v = v.replaceAll(/^0\d$/g, '0')
  // 只匹配数字
  v = v.replaceAll(/\D/g, '')
  // 返回结果
  return v
}

/**
 * 去掉中文及空格
 * @param {string} value 当前值字符串
 * @returns {string} 返回处理后的字符串
 */
export function verifyCnAndSpace(value: string) {
  // 匹配中文与空格
  let v = value.replaceAll(/[\s\u4E00-\u9FA5]+/g, '')
  // 匹配空格
  v = v.replaceAll(/(^\s*)|(\s*$)/g, '')
  // 返回结果
  return v
}

/**
 * 去掉英文及空格
 * @param {string} value 当前值字符串
 * @returns {string} 返回处理后的字符串
 */
export function verifyEnAndSpace(value: string) {
  // 匹配英文与空格
  let v = value.replaceAll(/[A-Za-z]+/g, '')
  // 匹配空格
  v = v.replaceAll(/(^\s*)|(\s*$)/g, '')
  // 返回结果
  return v
}

/**
 * 禁止输入空格
 * @param {string} value 当前值字符串
 * @returns {string} 返回处理后的字符串
 */
export function verifyAndSpace(value: string) {
  // 匹配空格
  const v = value.replaceAll(/(^\s*)|(\s*$)/g, '')
  // 返回结果
  return v
}

/**
 * 金额用 `,` 区分开
 * @param {string} value 当前值字符串
 * @returns {string} 返回处理后的字符串
 */
export function verifyNumberComma(value: string) {
  // 调用小数或整数(不可以负数)方法
  let v: any = verifyNumberIntegerAndFloat(value)
  // 字符串转成数组
  v = v.toString().split('.')
  // \B 匹配非单词边界，两边都是单词字符或者两边都是非单词字符
  v[0] = v[0].replaceAll(/\B(?=(\d{3})+(?!\d))/g, ',')
  // 数组转字符串
  v = v.join('.')
  // 返回结果
  return v
}

/**
 * 匹配文字变色（搜索时）
 * @param {string} value 当前值字符串
 * @param {string} text 要处理的字符串值
 * @param {string} color 搜索到时字体高亮颜色
 * @returns {string} 返回处理后的字符串
 */
export function verifyTextColor(value: string, text = '', color = 'red') {
  // 返回内容，添加颜色
  const v = text.replaceAll(
    new RegExp(value, 'gi'),
    `<span style='color: ${color}'>${value}</span>`
  )
  // 返回结果
  return v
}

/**
 * 数字转中文大写
 * @param {string} value 当前值字符串
 * @param {string} unit 默认：仟佰拾亿仟佰拾万仟佰拾元角分
 * @param {string} v 中间变量，缓存处理结果
 * @returns {string} 返回处理后的字符串
 */
export function verifyNumberCnUppercase(
  value: any,
  unit = '仟佰拾亿仟佰拾万仟佰拾元角分',
  v = ''
) {
  // 当前内容字符串添加 2个0，为什么??
  value += '00'
  // 返回某个指定的字符串值在字符串中首次出现的位置，没有出现，则该方法返回 -1
  const lookup = value.indexOf('.')
  // substring：不包含结束下标内容，substr：包含结束下标内容
  if (lookup >= 0) {
    value = value.slice(0, Math.max(0, lookup)) + value.substr(lookup + 1, 2)
  }
  // 根据内容 val 的长度，截取返回对应大写
  unit = unit.slice(unit.length - value.length)
  // 循环截取拼接大写
  for (let index = 0; index < value.length; index++) {
    v += '零壹贰叁肆伍陆柒捌玖'.substr(value.substr(index, 1), 1) + unit.substr(index, 1)
  }
  // 正则处理
  v = v
    .replace(/零角零分$/, '整')
    .replaceAll(/零[仟佰拾]/g, '零')
    .replaceAll(/零{2,}/g, '零')
    .replaceAll(/零([|万亿])/g, '$1')
    .replace(/零+元/, '元')
    .replace(/亿零{0,3}万/, '亿')
    .replace(/^元/, '零元')
  // 返回结果
  return v
}

/**
 * 手机号码
 * @param {string} value 当前值字符串
 * @returns {boolean} 返回 true: 手机号码正确
 */
export function verifyPhone(value: string) {
  return /^((12\d)|(13\d)|(14[57|])|(15([0-3]|[5-9]))|(18[,015-9|]))\d{8}$/
    .test(value)
}

/**
 * 国内电话号码
 * @param {string} value 当前值字符串
 * @returns {boolean} 返回 true: 国内电话号码正确
 */
export function verifyTelPhone(value: string) {
  return /\d{3}-\d{8}|\d{4}-\d{7}/.test(value)
}

/**
 * 登录账号 (字母开头，允许5-16字节，允许字母数字下划线)
 * @param {string} value 当前值字符串
 * @returns {boolean} 返回 true: 登录账号正确
 */
export function verifyAccount(value: string) {
  return /^[A-Za-z]\w{4,15}$/.test(value)
}

/**
 * 密码 (以字母开头，长度在6~16之间，只能包含字母、数字和下划线)
 * @param {string} value 当前值字符串
 * @returns {boolean} 返回 true: 密码正确
 */
export function verifyPassword(value: string) {
  return /^[A-Za-z]\w{5,15}$/.test(value)
}

/**
 * 强密码 (字母+数字+特殊字符，长度在6-16之间)
 * @param {string} value 当前值字符串
 * @returns {boolean} 返回 true: 强密码正确
 */
export function verifyPasswordPowerful(value: string) {
  return /^(?![A-z]+$)(?!\d+$)(?![!#$%&*.@^]+$)(?![\dA-z]+$)(?![!#$%&*.@A-z]+$)(?![\d!#$%&*.@^]+$)[\d!#$%&*.@A-Z^a-z]{6,16}$/
    .test(value)
}

/**
 * 密码强度
 * @description 弱：纯数字，纯字母，纯特殊字符
 * @description 中：字母+数字，字母+特殊字符，数字+特殊字符
 * @description 强：字母+数字+特殊字符
 * @param {string} value 当前值字符串
 * @returns {boolean}  返回处理后的字符串：弱、中、强
 */
export function verifyPasswordStrength(value: string) {
  let v = ''
  // 弱：纯数字，纯字母，纯特殊字符
  if (/^(?:\d+|[A-Za-z]+|[!#$%&*.@^]+){6,16}$/.test(value)) {
    v = '弱'
  }
  // 中：字母+数字，字母+特殊字符，数字+特殊字符
  if (
    /^(?![A-z]+$)(?!\d+$)(?![!#$%&*.@^]+$)[\d!#$%&*.@A-Z^a-z]{6,16}$/.test(
      value
    )
  ) {
    v = '中'
  }
  // 强：字母+数字+特殊字符
  if (
    /^(?![A-z]+$)(?!\d+$)(?![!#$%&*.@^]+$)(?![\dA-z]+$)(?![!#$%&*.@A-z]+$)(?![\d!#$%&*.@^]+$)[\d!#$%&*.@A-Z^a-z]{6,16}$/.test(
      value
    )
  ) {
    v = '强'
  }
  // 返回结果
  return v
}

/**
 * IP地址
 * @param {string} value 当前值字符串
 * @returns {boolean}  返回 true: IP地址正确
 */
export function verifyIPAddress(value: string) {
  return /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/
    .test(value)
}

/**
 * 邮箱
 * @param {string} value 当前值字符串
 * @returns {boolean} 返回 true: 邮箱正确
 */
export function verifyEmail(value: string) {
  return /^(([^\s"(),.:;<>@[\\\]]+(\.[^\s"(),.:;<>@[\\\]]+)*)|(".+"))@((\[(?:\d{1,3}\.){3}\d{1,3}])|(([\dA-Za-z\-]+\.)+[A-Za-z]{2,}))$/
    .test(value)
}

/**
 * @description 中国大陆身份证校验
 * @param idCard 身份证号码
 * @returns {boolean} 返回身份证是否正确
 */
export function verifyIdCardChina(idCard: string) {
  // 加权因子
  const weightFactor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
  // 校验码
  const checkCode = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']
  const code = `${idCard}`
  const last = idCard[17]
  const seventeen = code.substring(0, 17)
  // ISO 7064:1983.MOD 11-2
  // 判断最后一位校验位
  const arr = [...seventeen]
  let num = 0
  for (const [index, item] of arr.entries()) {
    num += Number.parseInt(item, 10) * weightFactor[index]
  }
  // 获取余数
  const module = num % 11
  // 返回结果
  return last === checkCode[module]
}
/**
 * 姓名
 * @param {string} value 当前值字符串
 * @returns {boolean} 返回 true: 姓名正确
 */
export function verifyFullName(value: string) {
  return /^[\u4E00-\u9FA5]{1,6}(·[\u4E00-\u9FA5]{1,6}){0,2}$/.test(value)
}

/**
 * 邮政编码
 * @param {string} value 当前值字符串
 * @returns {boolean} 返回 true: 邮政编码正确
 */
export function verifyPostalCode(value: string) {
  // false: 邮政编码不正确
  return /^[1-9]\d{5}$/.test(value)
}

/**
 * url 处理
 * @param {string} value 当前值字符串
 * @returns {boolean} 返回 true: url 正确
 */
export function verifyUrl(value: string) {
  return /^(((ht|f)tps?):\/{2})?([^\s!#$%&*.?@^-]([^\s!#$%&*.?@^]{1,64})?\.)+[a-z]{2,6}\/?/.test(value)
}

/**
 * 车牌号
 * @param {string} value 当前值字符串
 * @returns {boolean} 返回 true：车牌号正确
 */
export function verifyCarNumber(value: string) {
  return /^[云京使冀吉宁川新晋桂沪津浙渝湘琼甘皖粤苏蒙藏豫贵赣辽鄂闽陕青领鲁黑][A-HJ-NP-Z][\dA-HJ-NP-Z]{4,5}[\dA-HJ-NP-Z学挂港澳警]$/.test(value)
}
